<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Procedures in Tcl</title>
<link rel="stylesheet" href="/cfg/format.css" type="text/css">
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="keywords" content="Tcl, learn Tcl, procedures, tutorial, programming language">
<meta name="description" content="This chapter of the Tcl tutorial covers Tcl procedures.">
<meta name="language" content="en">
<meta name="author" content="Jan Bodnar">
<meta name="distribution" content="global">

<script type="text/javascript" src="/lib/jquery.js"></script>
<script type="text/javascript" src="/lib/common.js"></script>

</head>

<body>

<div class="container">

<div id="wide_ad" class="ltow">
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* 160x600, August 2011 */
google_ad_slot = "2484182563";
google_ad_width = 160;
google_ad_height = 600;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>

<div class="content">

<a href="/" title="Home">Home</a>&nbsp;
<a href="..">Contents</a>


<h1>Procedures in Tcl</h1>

<p>
In this part of the tutorial, we will cover Tcl procedures. 
</p>

<script type="text/javascript"><!--
google_ad_client = "ca-pub-9706709751191532";
/* LargeSquare */
google_ad_slot = "5070696322";
google_ad_width = 336;
google_ad_height = 280;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>

<p>
A procedure is a code block containing a series of commands. 
Procedures are called functions in some programming languages.
It is a good programming practice that procedures do only one specific 
task. Procedures bring modularity to programs. Proper use of
procedures bring the following advantages:
</p>


<ul>
  <li>Reducing duplication of code</li>
  <li>Decomposing complex problems into simpler pieces</li>
  <li>Improving clarity of the code</li>
  <li>Reuse of code</li>
  <li>Information hiding</li>
</ul>

<p>
There are two basic types of procedures. Built-in procedures and user defined ones. 
The built-in procedures are part of the Tcl core language. Examples are: rand(), 
sin() or exp(). The user defined functions are functions created 
with the proc keyword.
</p>

<p>
The term procedures and commands are often used interchangeably. In other words,
the proc keyword is used to create new Tcl commands. 
</p>

<p>
We start with a simple example. 
</p>

<pre class="code">
#!/usr/bin/tclsh

proc tclver {} {

    set v [info tclversion]
    puts "this is tcl version $v"
}

tclver
</pre>

<p>
In this script, we create a simple tclver procedure.
The procedure prints the version of Tcl language. 
</p>

<pre class="explanation">
proc tclver {} {
</pre>

<p>
The new procedure is created with the <code>proc</code> command. 
The {} characters tell us, that the procedure takes no arguments. 
</p>

<pre class="explanation">
    {

    set v [info tclversion]
    puts "this is tcl version $v"
}
</pre>

<p>
This is the body of the tclver procedure. It is executed, when
we execute the tclver command. The body of the command lies between
the curly brackets. 
</p>

<pre class="explanation">
tclver
</pre>

<p>
The procedure is called by specifying its name. 
</p>

<pre>
$ ./version.tcl 
this is tcl version 8.5
</pre>

<p>
Sample output. 
</p>

<h2>Procedure arguments</h2>

<p>
An argument is a value passed to the procedure.
Procedures can take one or more arguments. If procedures work with data, we must
pass the data to the procedures. 
</p>

<p>
In the following example, we have a procedure which
takes one argument. 
</p>

<pre class="code">
#!/usr/bin/tclsh

proc ftc {f} {

    return [expr $f * 9 / 5 + 32]
}

puts [ftc 100]
puts [ftc 0]
puts [ftc 30]
</pre>

<p>
We create a ftc procedure, which transforms fahrenheit
temperature to celsius temperature. 
</p>

<pre class="explanation">
proc ftc {f} {
</pre>

<p>
The procedure takes one parameter. Its name f will be used
in the body of the procedure. 
</p>

<pre class="explanation">
return [expr $f * 9 / 5 + 32]
</pre>

<p>
We compute the value of the celsius temperature. The <code>return</code>
command returns the value to the caller. If the procedure doesn't execute 
an explicit return, then its return value is the value of the last command 
executed in the procedure's body. 
</p>

<pre class="explanation">
puts [ftc 100]
</pre>

<p>
The ftc procedure is executed. It takes 100 as a parameter. It is the
temperature in fahrenheit. The returned value is used by the <code>puts</code>
command, which prints it to the console. 
</p>

<pre>
$ ./fahrenheit.tcl
212
32
86
</pre>

<p>
Output. 
</p>


<hr class="btm">

<p>
Next we will have a procedure, which takes two arguments. 
</p>

<pre class="code">
#!/usr/bin/tclsh

proc maximum {x y} {
    
    if {$x > $y} {

        return $x
    } else {
        
        return $y
    }
}

set a 23
set b 32

set val [maximum $a $b]
puts "The max of $a, $b is $val"
</pre>

<p>
We have a maximum procedure, which returns the maximum of two values. 
</p>

<pre class="explanation">
proc maximum {x y} {
</pre>

<p>
The method takes two arguments. 
</p>

<pre class="explanation">
if {$x > $y} {

    return $x
} else {
    
    return $y
}
</pre>

<p>
Here we compute which number is greater. 
</p>

<pre class="explanation">
set a 23
set b 32
</pre>

<p>
We define two variables, which are to be compared. 
</p>

<pre class="explanation">
set val [maximum $a $b]
</pre>

<p>
We calculate the maximum of the two variables. 
</p>

<pre>
$ ./maximum.tcl
The max of 23, 32 is 32
</pre>

<p>
Output.
</p>

<h2>Variable number of arguments</h2>

<p>
A procedure can take and process variable number of arguments. 
For this we use the special <code>args</code> argument. 
</p>

<pre class="code">
#!/usr/bin/tclsh

proc sum {args} {

    set s 0

    foreach arg $args {

        incr s $arg
    }

    return $s
}

puts [sum 1 2 3 4]
puts [sum 1 2]
puts [sum 4]
</pre>

<p>
We define a sum procedure which adds up all its arguments. 
</p>

<pre class="explanation">
proc sum {args} {
</pre>

<p>
The sum procedure has a special <code>args</code> argument. It has a list
of all values passed to the procedure. 
</p>

<pre class="explanation">
foreach arg $args {

    incr s $arg
}
</pre>

<p>
We go through the list and calculate the sum. 
</p>

<pre class="explanation">
puts [sum 1 2 3 4]
puts [sum 1 2]
puts [sum 4]
</pre>

<p>
We call the sum procedure three times. In the first case, it takes 
4 arguments, in the second case 2, in the last case one. 
We call the same method.
</p>

<pre>
$ ./variable.tcl
10
3
4
</pre>

<p>
Output.
</p>


<h2>Implicit arguments</h2>

<p>
The arguments in Tcl procedures may have implicit values. 
An implicit value is used, if no explicit value is provided.
</p>

<pre class="code">
#!/usr/bin/tclsh

proc power {a {b 2}} {

    if {$b == 2} {
        return [expr $a * $a]
    }

    set value 1

    for {set i 0} {$i&lt;$b} {incr i} {

        set value [expr $value * $a]
    }

    return $value
}

set v1 [power 5]
set v2 [power 5 4]

puts "5^2 is $v1"
puts "5^4 is $v2"
</pre>

<p>
Here we create a power procedure. 
The procedure has one argument with an implicit value. 
We can call the procedure with one or two arguments.
</p>

<pre class="explanation">
proc power {a {b 2}} {
</pre>

<p>
The second argument b, has an implicit value 2. If we provide only
one argument, the power procedure then returns the value of a to 
the power 2.
</p>

<pre class="explanation">
set v1 [power 5]
set v2 [power 5 4]
</pre>

<p>
We call the power procedure with one and two arguments. 
The first line computes the value of 5 to the power 2. The
second line value of 5 to the power 4. 
</p>

<pre>
$ ./implicit.tcl
5^2 is 25
5^4 is 625
</pre>

<p>
Output.
</p>


<h2>Recursion</h2>

<p>
Recursion, in mathematics and computer science, is a way of 
defining functions in which the function being defined is applied 
within its own definition. In other words, a recursive function 
calls itself to do its job. Recursion is a widely used approach 
to solve many programming tasks. 
</p>

<p>
Recursion calls have a limit in Tcl. There cannot be more than
1000 recursion calls. 
</p>

<p>
A typical example of recursion is calculation of the factorial.
Factorial n!, is the product of all positive integers less than or 
equal to n.
</p>

<pre class="code">
#!/usr/bin/tclsh

proc factorial n {

    if {$n==0} {

        return 1
    } else {

        return [expr $n * [factorial [expr $n - 1]]]
    }
}

# Stack limit between 800 and 1000 levels

puts [factorial 4]
puts [factorial 10]
puts [factorial 18]
</pre>

<p>
In this code example, we calculate the factorial of three
numbers. 
</p>

<pre class="explanation">
return [expr $n * [factorial [expr $n - 1]]]
</pre>

<p>
Inside the body of the factorial procedure, we call the factorial procedure
with a modified argument. The procedure calls itself.
</p>

<pre>
$ ./recursion.tcl
24
3628800
6402373705728000
</pre>

<p>
These are the results. If we tried to compute the factorial of 100, we would receive
"too many nested evaluations" error. 
</p>


<h2>Scope</h2>

<p>
A variable declared inside a procedure has a procedure scope.
The <b>scope</b> of a name is the region of program text within which it 
is possible to refer to the entity declared by the name without qualification 
of the name. A variable which is declared inside a procedure has a procedure
scope. It is also called a local scope. The variable  is valid only in 
this particular procedure.
</p>

<pre class="code">
#!/usr/bin/tclsh

proc test {} {

    puts "inside procedure"
    #puts "x is $x"
    set x 4
    puts "x is $x"
}

set x 1

puts "outside procedure"
puts "x is $x"

test

puts "outside procedure"
puts "x is $x"
</pre>

<p>
In the preceding example, we have an x variable defined outside and 
inside of the test procedure.
</p>

<pre class="explanation">
set x 4
puts "x is $x"
</pre>

<p>
Inside the test procedure, we define an x variable. The variable has
local scope. It is valid only inside this procedure. 
</p>

<pre class="explanation">
set x 1

puts "outside procedure"
puts "x is $x"
</pre>

<p>
We define an x variable outside the procedure. It has a global scope. 
The variables do not conflict, because they have different scopes. 
</p>

<pre>
$ ./scope.tcl
outside procedure
x is 1
inside procedure
x is 4
outside procedure
x is 1
</pre>

<p>
Output.
</p>

<hr class="btm">

<p>
It is possible to change the global variable inside
a procedure. 
</p>

<pre class="code">
#!/usr/bin/tclsh

proc test {} {

    upvar x y
    puts "inside procedure"
    puts "y is $y"
    set y 4
    puts "y is $y"
}

set x 1

puts "outside procedure"
puts "x is $x"

test

puts "outside procedure"
puts "x is $x"
</pre>

<p>
We define a global x variable. We change the variable inside the
test procedure. 
</p>

<pre class="explanation">
upvar x y
</pre>

<p>
We refer to the global x variable by the name y with 
the <code>upvar</code> command. 
</p>

<pre class="explanation">
set y 4
</pre>

<p>
We assign a value to the local y variable and also change the value
of the global x variable. 
</p>

<pre>
$ ./scope2.tcl
outside procedure
x is 1
inside procedure
y is 1
y is 4
outside procedure
x is 4
</pre>

<p>
From the output we can see, that the test procedure has changed the
x variable. 
</p>

<hr class="btm">

<p>
With the <code>global</code> command, we can refer to global
variables from procedures. 
</p>

<pre class="code">
#!/usr/bin/tclsh

proc test {} {

    global x 
    puts "inside test procedure x is $x"

    proc nested {} {
        global x
        puts "inside nested x is $x"
    }
}

set x 1

test
nested

puts "outside x is $x"
</pre>

<p>
In the above example, we have a test procedure and a nested
procedure defined within the test procedure. We refer to the
global x variable from both procedures. 
</p>

<pre class="explanation">
global x 
puts "inside test procedure x is $x"
</pre>

<p>
With the <code>global</code> command, we refer to the global
x variable, defined outside the test procedure. 
</p>

<pre class="explanation">
proc nested {} {
    global x
    puts "inside nested x is $x"
}
</pre>

<p>
It is possible to create nested procedures. These are procedures defined
inside other procedures. We refer to the global x variable with 
the <code>global</code> command. 
</p>

<pre class="explanation">
test
nested
</pre>

<p>
We call the test procedure and its nested procedure. 
</p>

<pre>
$ ./scope3.tcl
inside test procedure x is 1
inside nested x is 1
outside x is 1
</pre>

<p>
Output. 
</p>


<p>
In this part of the Tcl tutorial, we covered Tcl procedures.
</p>


<br>
<div class="center"> 
<script type="text/javascript"><!--
google_ad_client = "pub-9706709751191532";
/* horizontal */
google_ad_slot = "1734478269";
google_ad_width = 468;
google_ad_height = 60;
//-->
</script> 
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> 
</script> 
</div> 
<br>


<div class="botNav, center">
<span class="botNavItem"><a href="/">Home</a></span> ‡ <span class="botNavItem">
<a href="..">Contents</a></span> ‡ <span class="botNavItem"><a href="#">Top of Page</a></span>
</div>


<div class="footer">
<div class="signature">
<a href="/">ZetCode</a> last modified April 16, 2011  <span class="copyright">&copy; 2007 - 2013 Jan Bodnar</span>
</div>
</div>

</div> <!-- content -->

</div> <!-- container -->

</body>
</html>
